package Engine.World;

import java.lang.Thread.State;
import java.util.ArrayList;
import java.util.Random;

import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector2f;
import org.newdawn.slick.opengl.Texture;

import Engine.Engine;
import Engine.Funktions;
import Engine.RenderObject;
import Engine.Blocks.*;

import Engine.PhysicEngine.PhysicObject;
import Engine.PhysicEngine.PlayerController;

public abstract class World extends RenderObject {

	// _______________ Y X

	Chunk chunks[];
	public PlayerController player;
	private Texture texture;
	private Vector2f PlayerSpawn = new Vector2f(32, 32);
	private int offset = 0;// 32768;
	public static int TerrainHeight = 128;
	int ChunkStart, ChunkEnd;

	public World(Engine engine) {

		chunks = new Chunk[65536];

	}

	public int seed = 93;

	@Override
	public void RenderObject_init() {
		seed = (int) (RandomYHeight(seed) * 200);
		Random random = new Random();

		setTexture(Funktions.loadTexture("World/misa.png", GL11.GL_NEAREST));

		int PlayerChunk = (int) (PlayerSpawn.x / 16.0f);
		ChunkStart = offset + PlayerChunk - 4;

		ChunkEnd = offset + PlayerChunk + 4;
		if (ChunkStart < 0)
			ChunkStart = 0;
		if (ChunkEnd > 65536)
			ChunkStart = 65536;
		for (int x = ChunkStart; x <= ChunkEnd; x++) {
			chunks[x] = new Chunk();
			chunks[x].Generate(seed, x, random);

		}

		World_init();
	}

	/*
	 * r1 = 0 r2 | 0.5 0.7 | | 1 6
	 */

	double r1, r2 = 0;

	private double RandomYHeight(int x) {

		return 1.0 - ((x * (x * x * 15731 + 789221) + 1376312589) * 0x7fffffff) / 1073741824.0;
	}

	public double Cosine_Interpolate(double a, double b, double x) {
		double ft = x * 3.1415927;
		double f = (1 - Math.cos(ft)) * .5;

		return a * (1 - f) + b * f;
	}

	@Override
	public void RenderObject_gui() {
		// TODO Auto-generated method stub

	}

	public abstract void World_init();

	@Override
	public void RenderObject_draw() {

		int PlayerChunk = 0;
		try {
			PlayerChunk = (int) (player.getxPosition() / (16.0f * 16.0f));
		} catch (java.lang.NullPointerException ex) {

		}

		int Viewrange = (int) ((Display.getWidth() * 0.5) / (16 * player.engine.zoom));
		// System.out.println(ChunkEnd-ChunkStart);
		ChunkStart = offset + PlayerChunk - Viewrange;

		ChunkEnd = offset + PlayerChunk + Viewrange;
		if (ChunkStart < 0)
			ChunkStart = 0;
		if (ChunkEnd > 65536)
			ChunkEnd = 65536;

		DrawInfos di = new DrawInfos(texture, getPlayer());
		for (int x = ChunkStart; x <= ChunkEnd; x++) {

			if (chunks[x] != null) {
				chunks[x].Draw(x - offset, di);
			} else {
				chunks[x] = new Chunk();
				chunks[x].Generate(seed, x, new Random());
				System.out.println("New Chunk added");
			}

		}
	
		World_draw();

	}

	public abstract void World_draw();

	public DefaultBlock getBlockAt(int X, int Y) {
		try {
			short Chunk = 0;
			if (X < 0)
				X -= 1;
			while (X <= 0) {
				Chunk--;
				X += 16;
			}
			while (X >= 16) {
				Chunk++;
				X -= 16;

			}

			return chunks[offset + Chunk].getBlockAt(X, Y);

		} catch (Exception ex) {
			// System.out.println("No in Terrain Physic: X: " + X + " Y: " + Y);
			return new Air();
		}

	}

	public PlayerController getPlayer() {
		return player;
	}

	public void setPlayer(PlayerController player) {
		this.player = player;
	}

	public Texture getTexture() {
		return texture;
	}

	public void setTexture(Texture texture) {
		this.texture = texture;
	}
}
